package com.yejing.urlconn;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class LimsHttpUtils {

    private static final String TOKEN_URL =
            "http://localhost:8881/LIMS-Server/MPLM_Service_Gateway/TokenGenerator/getToken";
    private static final String U_NAME = "ex_cuiml1";
    private static final String F_NAME = "getTestForm";

    private static final String CHARSET = "UTF-8";


    public static void main(String[] args) {

    }


    public String getOrgDataListFromLims()
            throws Exception {
        String url_s = "http://localhost:8881/LIMS-Server/MPLM_Service_Gateway/MeixinTestFormController/findBusiness";
        String result = null; // 返回结果字符串
        HttpURLConnection conn = buildLimsConn(url_s);
        String params = "__TokenAuthorization_UserName_="+U_NAME;
        connPostForm(conn,params);
        result = requestAndGetResult(conn);
        return result;
    }


    public String startTest() throws Exception {
        String url_s = "http://localhost:8881/LIMS-Server/MPLM_Service_Gateway/AppTestProcessController/startTest";
        HttpURLConnection conn = buildLimsConn(url_s);
        StringBuffer params = new StringBuffer();
        params.append("__TokenAuthorization_UserName_="+U_NAME);
        params.append("&buId=17");
        params.append("&list=[{\"delegateNumber\":\"PT2023050063\",\"executor\":\"ex_cuiml1\",\"sampleNumber\":\"1\",\"equipmentCode\":\"\",\"projectCode\":\"52004245493\",\"page\":1,\"rows\":20,\"buId\":17,\"jdq\":\"true\",\"ctlIdx\":1,\"status\":1,\"testCondition\":\"外壳强度（针对有端子插片）测试后性能\",\"executor\":\"1\"}]");
        connPostForm(conn,params.toString());
        String result = requestAndGetResult(conn);
        return result;
    }

    public String writeDataToDevice() throws Exception{
        String url_s = "https://10.16.115.29:13900/edge/manager/device/writeDataToDevice";
        HttpURLConnection conn = buildLimsConn(url_s);
        String params = "{\"propertyCode\":\"START000001\",\"propertyValue\":\"111\",\"deviceCode\":\"A2202020122200001\",\"time\":1686900315408}";
        connPostJson(conn,params);
        String result = requestAndGetResult(conn);
        return result;
    }


    private HttpURLConnection buildLimsConn(String url_s) throws Exception {
        HttpURLConnection conn = null;
        URL url = new URL(url_s);
        String protocol = url.getProtocol();
        if (protocol.equals("https")) {
            conn = getHttpsURLConnection(url_s);
        } else {
            conn = getHttpURLConnection(url_s);
        }
        HashMap<String,String> headers = new HashMap<>();
        headers.put("__TokenAuthorization_UserName_",U_NAME);
        headers.put("__TokenAuthorization_Function_",F_NAME);
        headers.put("__TokenAuthorization_UID_", getToken());
        connSetHeaders(conn,headers);
        return conn;
    }

    public String getToken() throws Exception {
        String token = "";
        HttpURLConnection conn = buildTokenConn(TOKEN_URL);
        String result = requestAndGetResult(conn);
        if(StringUtils.isNoneBlank(result)){
            JSONObject jsonObject = JSONObject.parseObject(result);
            token = jsonObject.getString("token");
        }
        return token;
    }

    public HttpURLConnection buildTokenConn(String url_s) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        HttpURLConnection conn = null;
        URL url = new URL(url_s);
        String protocol = url.getProtocol();
        if (protocol.equals("https")) {
            conn = getHttpsURLConnection(url_s);
        } else {
            conn = getHttpURLConnection(url_s);
        }
        HashMap<String, String> header = new HashMap<>();
        header.put("__TokenAuthorization_Username_", U_NAME);
        header.put("__TokenAuthorization_Function_", F_NAME);
        connSetHeaders(conn, header);
        return conn;
    }

    private HttpURLConnection buildConn(String url_s) throws Exception {
        HttpURLConnection conn = null;
        URL url = new URL(url_s);
        String protocol = url.getProtocol();
        if (protocol.equals("https")) {
            conn = getHttpsURLConnection(url_s);
        } else {
            conn = getHttpURLConnection(url_s);
        }
        return conn;
    }

    private HttpURLConnection getHttpURLConnection(String requestUrl) throws IOException {
        // 创建远程url连接对象
        URL url = new URL(requestUrl);
        // 通过远程url连接对象打开一个连接，强转成httpURLConnection类
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        connInit(conn);
        return conn;
    }

    //
    private HttpURLConnection getHttpsURLConnection(String requestUrl) throws NoSuchAlgorithmException, IOException, KeyManagementException {
        //创建SSLContext
        SSLContext sslContext = SSLContext.getInstance("SSL");
        TrustManager[] tm = {new MyX509TrustManager()};
        //初始化
        sslContext.init(null, tm, new java.security.SecureRandom());
        //获取SSLSocketFactory对象
        SSLSocketFactory ssf = sslContext.getSocketFactory();
        URL url = new URL(requestUrl);
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        //设置当前实例使用的SSLSoctetFactory
        conn.setSSLSocketFactory(ssf);
        connInit(conn);
        return conn;
    }

    private void connInit(HttpURLConnection conn) {
        // 设置连接主机服务器的超时时间：15000毫秒
        conn.setConnectTimeout(15000);
        // 设置读取远程返回的数据时间：60000毫秒
        conn.setReadTimeout(60000);
        conn.setUseCaches(false);
        // 默认值为：false，当向远程服务器传送数据/写数据时，需要设置为true
        conn.setDoOutput(true);
        // 默认值为：true，当前向远程服务读取数据时，设置为true，该参数可有可无
        conn.setDoInput(true);
    }

    private void connPostForm(HttpURLConnection conn,String param) throws IOException {
        conn.setRequestMethod("POST");   //设置POST方式连接
        //设置请求属性
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Charset", "UTF-8");

        if(StringUtils.isNoneBlank(param)){
            writeParamsToConn(conn, param);
        }
    }




    private void connSetHeaders(HttpURLConnection conn, Map<String,String> headers){
        if(headers != null && headers.size()>0){
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
    }

    private void connPostJson(HttpURLConnection conn,String param) throws IOException{
        conn.setRequestMethod("POST");   //设置POST方式连接
        // 设置请求属性
        conn.setRequestProperty("Content-type", "application/json;charset=UTF-8");
        writeParamsToConn(conn, param);
    }

    private static void writeParamsToConn(HttpURLConnection conn, String param) throws IOException {
        // 建立输入流，向指向的URL传入参数
        // 把 out.writeBytes(content) 替换成 out.write(content.getBytes()) ，
        // 因为 java 里的 char 类型是16位（2个字节）的，一个 char 可以存储一个中文字符，
        // 在将其转换为 byte（1个字节）后高8位会丢失，这样就无法将中文字符串完整的输出到字节输出流中。
        // 所以在可能有中文字符输出的地方最好先将字符串转换为字节数组，
        // 然后再通过 write() 写入字节输出流。只能解决部分的问题，如果汉子是三个字节的或四个字节的，
        // 就有问题了
//        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
//        dos.write(param.getBytes(CHARSET));

        // 解决中文乱码的问题，
        // 思路是用字符流代替字节流进行传输，因为我们传入的JSON字符串是纯字符。
        // 这样就完美避开了用字节流传输包含中文的字符串时，可能存在的奇怪的转化问题。

        PrintWriter dos = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(),CHARSET));
        dos.println(param);
        dos.flush();
        dos.close();
    }

    /**
     * 发送请求，并且获取返回值
     * @param conn
     * @return
     * @throws IOException
     */
    private String requestAndGetResult(HttpURLConnection conn) throws IOException {
        String content = "";
        conn.connect(); // 发送请求
        int responseCode = conn.getResponseCode();
        if(responseCode == 200){
            // 读取服务器端返回的内容
            InputStream is = conn.getInputStream();
            InputStreamReader input = new InputStreamReader(is,CHARSET);
            BufferedReader buffer = new BufferedReader(input);
            String inputLine;
            StringBuffer resultData = new StringBuffer();
            while ((inputLine=buffer.readLine()) != null){
                resultData.append(inputLine);
            }
            content = resultData.toString();
        }else{
            log.error("responseCode:{}",responseCode);
        }
        return content;
    }

}
